package cn.imatu.framework.ip2region.handler;

import cn.imatu.framework.ip2region.model.AddressInfo;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * @author shenguangyang
 */
public class Ip2RegionImpl implements Ip2RegionHandler {
    private static final Logger log = LoggerFactory.getLogger(Ip2RegionImpl.class);
    private final byte[] vectorIndex;
    private final String databasePath;

    public Ip2RegionImpl(byte[] vectorIndex, String databasePath) {
        this.vectorIndex = vectorIndex;
        this.databasePath = databasePath;
    }

    @Override
    public AddressInfo getAddress(String ip) throws Exception {
        if (StringUtils.isEmpty(ip)) {
            return new AddressInfo();
        }
        // 2、使用全局的 vIndex 创建带 VectorIndex 缓存的查询对象。
        Searcher searcher;
        try {
            searcher = Searcher.newWithVectorIndex(databasePath, vectorIndex);
        } catch (Exception e) {
            log.error("failed to create vectorIndex cached searcher with [{}]: {}", databasePath, e.getMessage());
            throw e;
        }

        // 3、查询
        try {
            long sTime = System.nanoTime();
            // 中国|0|浙江省|杭州市|电信
            String region = searcher.search(ip);
            long cost = TimeUnit.NANOSECONDS.toMicros((System.nanoTime() - sTime));
            log.debug("ip: {}, region: {}, ioCount: {}, took: {} μs", ip, region, searcher.getIOCount(), cost);
            String[] split;
            if (StringUtils.isNotEmpty(region) && (split = region.split("\\|")).length >= 5) {
                return AddressInfo.builder().country(split[0]).province(split[2]).city(split[3]).isp(split[4]).build();
            }
        } catch (Exception e) {
            log.error("failed to search({}): {}", ip, e.getMessage());
            throw e;
        } finally {
            // 4、关闭资源
            searcher.close();
        }
        return new AddressInfo();
    }
}
